package com.bstech.Tabelle;

import java.io.StringWriter;
import java.util.List;
import java.util.Vector;

import org.acra.ErrorReporter;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlSerializer;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.bstech.Classi.Common;
import com.bstech.Tabelle.RapportiniDettaglio.RapportinoDettaglio;
import com.bstech.Tabelle.RapportiniTecnici.RapportinoTecnici;
import com.bstech.Utils.*;

public class Rapportini {
	public static String TABLE_NAME = "RAPPORTINI";
	
	public static String ID_KEY = "ID";
	public static String ID_CHIAMATA_KEY = "ID_CHIAMATA";
	public static String DATA_KEY = "DATA";
	public static String DESCRIZIONE_KEY = "DESCRIZIONE";
	public static String ORE_ORDINARIE_KEY = "ORE_ORDINARIE";
	public static String ORE_STRAORDINARIE_KEY = "ORE_STRAORDINARIE";
	public static String KM_KEY = "KM";
	public static String PASTI_KEY = "PASTI";
	public static String VIAGGIO_KEY = "VIAGGIO";
	public static String DIRITTO_CHIAMATA_KEY = "DIRITTO_CHIAMATA";
	public static String FESTIVO_KEY = "FESTIVO";
	public static String BOLLE_KEY = "BOLLE";
	public static String MODIFICATO_KEY = "MODIFICATO";
	
	
	public static String CREATE_TABLE_QUERY = "CREATE TABLE IF NOT EXISTS "+ TABLE_NAME +"(" +
												ID_KEY+" integer primary key not null," +
												ID_CHIAMATA_KEY+" integer not null," +
												DATA_KEY+" integer not null," +
												DESCRIZIONE_KEY+" text null," +
												ORE_ORDINARIE_KEY+" real not null," +
												ORE_STRAORDINARIE_KEY+" real not null," +
												KM_KEY+" integer not null," +
												PASTI_KEY+" integer not null," +
												VIAGGIO_KEY+" real not null," +
												DIRITTO_CHIAMATA_KEY+" integer not null," +
												FESTIVO_KEY+" integer null," +
												BOLLE_KEY+" text null," +
												MODIFICATO_KEY+" integer not null);";
	
	public static void UpdateToVersion(SQLiteDatabase db, int from, int to )
	{
		for(int ver = from +1; ver<= to; ver++)
		{
			switch(ver)
			{
			case 4:
				db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + FESTIVO_KEY + " integer null");
				break;
			}
		}
	}
	public static boolean Insert(int ID, int IdChiamata, long Data, String Descrizione,double OreOrdinarie, double OreStraordinarie,int Km, int Pasti, double Viaggio, int DirittoChiamata, int Festivo, String Bolle, boolean Modificato)
	{
		ContentValues cv = new ContentValues();
		
		cv.put(Rapportini.ID_KEY, ID);
		cv.put(Rapportini.ID_CHIAMATA_KEY, IdChiamata);
		cv.put(Rapportini.DATA_KEY, Data);
		cv.put(Rapportini.DESCRIZIONE_KEY, Strings.CheckString(Descrizione));
		cv.put(Rapportini.ORE_ORDINARIE_KEY, OreOrdinarie);
		cv.put(Rapportini.ORE_STRAORDINARIE_KEY, OreStraordinarie);
		cv.put(Rapportini.KM_KEY, Km);
		cv.put(Rapportini.PASTI_KEY, Pasti);
		cv.put(Rapportini.VIAGGIO_KEY, Viaggio);
		cv.put(Rapportini.DIRITTO_CHIAMATA_KEY, DirittoChiamata);
		cv.put(Rapportini.FESTIVO_KEY, Festivo);
		cv.put(Rapportini.BOLLE_KEY, Strings.CheckString(Bolle));
		cv.put(Rapportini.MODIFICATO_KEY, Modificato ? -1 : 0);
		
		Log.v("Insert Rapportino", "ID: " + Integer.toString(ID) + " IDChiamata: " + Integer.toString(IdChiamata));
		return Common.db.Insert(Rapportini.TABLE_NAME, null, cv);
	}	
	public static boolean Update(Rapportino rapp)
	{
		return Update(rapp.ID,rapp.IdChiamata,rapp.Data,rapp.Descrizione,rapp.OreOrdinarie,rapp.OreStraordinarie,rapp.Km,rapp.Pasti,rapp.Viaggio,rapp.DirittoChiamata,rapp.Festivo,rapp.Bolle,true);
	}
	public static boolean Update(int ID, int IdChiamata, long Data, String Descrizione,double OreOrdinarie,double OreStraordinarie,int Km, int Pasti, double Viaggio, int DirittoChiamata, int Festivo, String Bolle, boolean modificato)
	{
		ContentValues cv = new ContentValues();
		
		cv.put(Rapportini.ID_CHIAMATA_KEY, IdChiamata);
		cv.put(Rapportini.DATA_KEY, Data);
		cv.put(Rapportini.DESCRIZIONE_KEY, Strings.CheckString(Descrizione));
		cv.put(Rapportini.ORE_ORDINARIE_KEY, OreOrdinarie);
		cv.put(Rapportini.ORE_STRAORDINARIE_KEY, OreStraordinarie);
		cv.put(Rapportini.KM_KEY, Km);
		cv.put(Rapportini.PASTI_KEY, Pasti);
		cv.put(Rapportini.VIAGGIO_KEY, Viaggio);
		cv.put(Rapportini.DIRITTO_CHIAMATA_KEY, DirittoChiamata);
		cv.put(Rapportini.FESTIVO_KEY, Festivo);
		cv.put(Rapportini.BOLLE_KEY, Strings.CheckString(Bolle));
		cv.put(Rapportini.MODIFICATO_KEY, modificato ? -1 : 0);
		
		Log.v("Update Rapportino", "ID: " + Integer.toString(ID) + " IDChiamata: " + Integer.toString(IdChiamata));
		return Common.db.Update(Rapportini.TABLE_NAME, cv, Rapportini.ID_KEY +" = " + Integer.toString(ID), null);
	}		
	public static Rapportino Select(int ID)
	{
		Cursor cursor = Common.db.query(Rapportini.TABLE_NAME, new String[] {Rapportini.ID_KEY,Rapportini.ID_CHIAMATA_KEY,Rapportini.DATA_KEY,Rapportini.DESCRIZIONE_KEY,
																			 Rapportini.ORE_ORDINARIE_KEY,Rapportini.ORE_STRAORDINARIE_KEY,Rapportini.KM_KEY,Rapportini.PASTI_KEY,
																			 Rapportini.VIAGGIO_KEY,Rapportini.DIRITTO_CHIAMATA_KEY,Rapportini.FESTIVO_KEY,Rapportini.BOLLE_KEY},
				Rapportini.ID_KEY + "= " + Integer.toString(ID),
				null, null,null, null);

		if(cursor != null && cursor.moveToFirst())
		{
			Rapportino ret =  Select(cursor);
			cursor.close();
			return ret;
		}
		else
			return null;
	}
	public static List<Rapportino> SelectAll(int IdChiamata)
	{
		Cursor cursor = Common.db.query(Rapportini.TABLE_NAME, new String[] {Rapportini.ID_KEY,Rapportini.ID_CHIAMATA_KEY,Rapportini.DATA_KEY,Rapportini.DESCRIZIONE_KEY,
																			 Rapportini.ORE_ORDINARIE_KEY,Rapportini.ORE_STRAORDINARIE_KEY,Rapportini.KM_KEY,Rapportini.PASTI_KEY,
																			 Rapportini.VIAGGIO_KEY,Rapportini.DIRITTO_CHIAMATA_KEY,Rapportini.FESTIVO_KEY,Rapportini.BOLLE_KEY},
										Rapportini.ID_CHIAMATA_KEY + "=" + Integer.toString(IdChiamata),
										null, null,null, 
										Rapportini.DATA_KEY);
		
		List<Rapportino> ret = new Vector<Rapportino>();
		
		if(cursor != null)
		{
			while(cursor.moveToNext())
				ret.add(Select(cursor));
			cursor.close();
		}
		
		return ret;
	}
	public static Rapportino SelectFirst(int IdChiamata)
	{
		Cursor cursor = Common.db.query(Rapportini.TABLE_NAME, new String[] {Rapportini.ID_KEY,Rapportini.ID_CHIAMATA_KEY,Rapportini.DATA_KEY,Rapportini.DESCRIZIONE_KEY,
																			 Rapportini.ORE_ORDINARIE_KEY,Rapportini.ORE_STRAORDINARIE_KEY,Rapportini.KM_KEY,Rapportini.PASTI_KEY,
																			 Rapportini.VIAGGIO_KEY,Rapportini.DIRITTO_CHIAMATA_KEY,Rapportini.FESTIVO_KEY,Rapportini.BOLLE_KEY},
										Rapportini.ID_CHIAMATA_KEY + "=" + Integer.toString(IdChiamata),
										null, null,null, 
										Rapportini.DATA_KEY);
		
		Rapportino ret = null;
		
		if(cursor != null && cursor.moveToNext())
		{
			ret = Select(cursor);
			cursor.close();
		}
		
		return ret;
	}
	public static List<Rapportino> SelectAllModificati(int IdChiamata)
	{
		Cursor cursor = Common.db.query(Rapportini.TABLE_NAME, new String[] {Rapportini.ID_KEY,Rapportini.ID_CHIAMATA_KEY,Rapportini.DATA_KEY,Rapportini.DESCRIZIONE_KEY,
																			 Rapportini.ORE_ORDINARIE_KEY,Rapportini.ORE_STRAORDINARIE_KEY,Rapportini.KM_KEY,Rapportini.PASTI_KEY,
																			 Rapportini.VIAGGIO_KEY,Rapportini.DIRITTO_CHIAMATA_KEY,Rapportini.FESTIVO_KEY,Rapportini.BOLLE_KEY},
																			 Rapportini.ID_CHIAMATA_KEY + "=" + Integer.toString(IdChiamata) + " AND "+ Rapportini.MODIFICATO_KEY + "<> 0",
										null, null,null, 
										Rapportini.DATA_KEY);
		
		List<Rapportino> ret = new Vector<Rapportino>();
		
		if(cursor != null)
		{
			while(cursor.moveToNext())
				ret.add(Select(cursor));
			cursor.close();
		}
		
		return ret;
	}
	public static boolean Exists(int idRapportino)
	{
		Cursor cursor = Common.db.query(Rapportini.TABLE_NAME, new String[] {Rapportini.ID_KEY},Rapportini.ID_KEY + "= " + Integer.toString(idRapportino),null, null,null, null);
		
		int count = 0;
		if (cursor != null) {
			count = cursor.getCount();
			cursor.close();
		}
		return (count > 0);
	}
	public static int CreateNew(int idChiamata, int idTecnico)
	{
		Common.db.BeginTransaction();
		
		int idRapp = DbFunctions.GetNewID(Rapportini.TABLE_NAME);
		if(idRapp != 0)
		{
			//creo record su Rapportini
			if(Rapportini.Insert(idRapp, idChiamata, Dates.GetDate() , "", 0, 0, 0, 0, 0, 0, 0, "",true))
			{
				//creo record su RapportiniTecnici 
				int idRappTec = DbFunctions.GetNewID(RapportiniTecnici.TABLE_NAME);
				if(idRappTec != 0)
				{
					if(!RapportiniTecnici.Insert(idRappTec, idRapp, idTecnico, RapportiniTecnici.STATO_ASSEGNATO,true))
					{
						idRapp = 0;
						Log.e("Rapportini.CreateNew", "Errore inserimento record RapportinoTecnico, IdChiamata: " + Integer.toString(idChiamata) 
								+ " idTecnico: " + Integer.toString(idTecnico));
					}
				}
				else
				{
					idRapp = 0;
					Log.e("Rapportini.CreateNew", "Errore creazione ID record RapportinoTecnico, IdChiamata: " + Integer.toString(idChiamata) 
							+ " idTecnico: " + Integer.toString(idTecnico));	
				}
			}
			else
			{
				idRapp = 0;
				Log.e("Rapportini.CreateNew", "Errore inserimento record Rapportino, IdChiamata: " + Integer.toString(idChiamata) 
						+ " idTecnico: " + Integer.toString(idTecnico));	
			}
				
		}
		else
			Log.e("Rapportini.CreateNew", "Errore creazione ID nuovo rapportino, IdChiamata: " + Integer.toString(idChiamata) 
											+ " idTecnico: " + Integer.toString(idTecnico));
		
		if(idRapp != 0)
			Common.db.Commit();
		else
			Common.db.Rollback();
		
		return idRapp;
	}
	private static Rapportino Select(Cursor cursor)
	{
		Rapportino ret = null;
		
		if(cursor != null && !cursor.isAfterLast())
		{	
			ret = new Rapportino();
			
			ret.ID = cursor.getInt(0);
			ret.IdChiamata = cursor.getInt(1);
			ret.Data = cursor.getLong(2);
			ret.Descrizione = cursor.getString(3);
			ret.OreOrdinarie = cursor.getDouble(4);
			ret.OreStraordinarie = cursor.getDouble(5);
			ret.Km = cursor.getInt(6);
			ret.Pasti = cursor.getInt(7);
			ret.Viaggio = cursor.getDouble(8);
			ret.DirittoChiamata = cursor.getInt(9);
			ret.Festivo = cursor.getInt(10);
			ret.Bolle = cursor.getString(11);
		}
		return ret;
	}
	public static void Storicizza()
	{
		Common.db.executeSql("DELETE FROM "+ Rapportini.TABLE_NAME +" WHERE "+ Rapportini.MODIFICATO_KEY +" = 0");
	}
	
	public static class Rapportino
	{
		public Rapportino(){}
		public int ID,IdChiamata,Km,Pasti,DirittoChiamata,Festivo;
		public long Data;
		public double Viaggio,OreOrdinarie,OreStraordinarie;
		public String Descrizione,Bolle;
		
		public static String GetXml(Rapportino item)
		{
			String ret = null;
			
			XmlSerializer serializer = XmlParser.CreateSerializer();
	        StringWriter writer = new StringWriter();
	        
	        try {
	                serializer.setOutput(writer);
	                serializer.startDocument("UTF-8", true);

    				serializer.startTag("", "RAPPORTINO");
    				XmlParser.addTagAndValue(serializer, "ID",Integer.toString(item.ID));
    				XmlParser.addTagAndValue(serializer, "AS02_CHIAMATA_AS01", Integer.toString(item.IdChiamata));
    				XmlParser.addTagAndValue(serializer, "AS02_DATA", Dates.DateToDotNetString(item.Data));
    				XmlParser.addTagAndValue(serializer, "AS02_DESCRIZIONE", item.Descrizione);
    				XmlParser.addTagAndValue(serializer, "AS02_ORE_ORDINARIE", Double.toString(item.OreOrdinarie));
    				XmlParser.addTagAndValue(serializer, "AS02_ORE_STRAORDINARIE", Double.toString(item.OreStraordinarie));
    				XmlParser.addTagAndValue(serializer, "AS02_KM", Integer.toString(item.Km));
    				XmlParser.addTagAndValue(serializer, "AS02_VIAGGIO", Double.toString(item.Viaggio));
    				XmlParser.addTagAndValue(serializer, "AS02_DIRITTO_CHIAMATA", Integer.toString(item.DirittoChiamata));
    				XmlParser.addTagAndValue(serializer, "AS02_FESTIVO", Integer.toString(item.Festivo));
    				XmlParser.addTagAndValue(serializer, "AS02_BOLLE", item.Bolle);
    				serializer.endTag("", "RAPPORTINO");

	                serializer.endDocument();
	                ret = writer.toString();
	                
	                writer.close();
	                writer = null;
	                serializer = null;
	        } catch (Exception e) {
	        	Log.e("Rapportino.GetXml", "Errore durante la creazione di un nodo. Errore: " + e.toString());
				ErrorReporter.getInstance().handleException(e);
	        }
			
	        return ret;
		}
		public static List<Rapportino> GetFromXml(String xml)
		{
			List<Rapportino> ret = new Vector<Rapportino>();
			
			if(xml !=null)
			{
				NodeList nodi = XmlParser.ParseNodes(xml, "RAPPORTINO");
				if(nodi !=null)
				{
					int nodesCount = nodi.getLength();
					Rapportino t = null;
					
					for(int i=0; i < nodesCount; i++)
					{
						t = ParseFromXmlNode(nodi.item(i));
						if(t != null)
							ret.add(t);
					}
					
					t = null;
					nodi = null;
				}
				else
					Log.e("Rapportino.GetFromXml", "Errore durante il parse dei nodi, ritornato null");
			}
			else
				Log.e("Rapportino.GetFromXml", "Parametro xml nullo");
			
			return ret;
		}
		private static Rapportino ParseFromXmlNode(Node nodo) {
			Rapportino ret = new Rapportino();
			
			NodeList dettagli = nodo.getChildNodes();
			int detailsCount = dettagli.getLength();
			
			Element dettaglio = null;
			String nome = "";
			String valore = "";
			
			for(int i=0;i<detailsCount;i++)
			{
				try {
					if(dettagli.item(i).getNodeType() == Node.ELEMENT_NODE)
					{
						dettaglio = (Element)dettagli.item(i);
						nome = dettaglio.getNodeName();
						valore = dettaglio.getTextContent();
						
						if(nome.equals("ID"))
							ret.ID = Integer.parseInt(valore.trim());
						else if(nome.equals("AS02_CHIAMATA_AS01"))
							ret.IdChiamata = Integer.parseInt(valore.trim());
						else if(nome.equals("AS02_DATA"))
							ret.Data = Dates.DateFromDotNetString(valore.trim());
						else if(nome.equals("AS02_DESCRIZIONE"))
							ret.Descrizione = valore.trim();
						else if(nome.equals("AS02_ORE_ORDINARIE"))
							ret.OreOrdinarie = Double.parseDouble(valore.trim());
						else if(nome.equals("AS02_ORE_STRAORDINARIE"))
							ret.OreOrdinarie = Double.parseDouble(valore.trim());
						else if(nome.equals("AS02_KM"))
							ret.Km = Integer.parseInt(valore.trim());
						else if(nome.equals("AS02_VIAGGIO"))
							ret.Viaggio = Double.parseDouble(valore.trim());
						else if(nome.equals("AS02_DIRITTO_CHIAMATA"))
							ret.DirittoChiamata = Integer.parseInt(valore.trim());
						else if(nome.equals("AS02_FESTIVO"))
							ret.Festivo = Integer.parseInt(valore.trim());
						else if(nome.equals("AS02_BOLLE"))
							ret.Bolle = valore.trim();
					}
				} catch (Exception e) {
					Log.e("Rapportino.ParseFromXmlNode", "Errore nel ciclo di assegnazione valori. Errore: " + e.toString());
					ret = null;
					break;
				}
			}
			
			dettaglio = null;
			dettagli = null;
			
			return ret;
		}
		public boolean ImpostaModificato(boolean stato)
		{
			try {
				ContentValues cv = new ContentValues();
				cv.put(Rapportini.MODIFICATO_KEY, stato ? -1 : 0);
				
				Log.v("Update flag MODIFICATO Rapportino", "IDRapportino: " + Integer.toString(ID));
				return Common.db.Update(Rapportini.TABLE_NAME, cv, Rapportini.ID_KEY + " = " + Integer.toString(ID), null);
			} catch (Exception e) {
				return false;
			}
		}
		public boolean AggiornaID(int nuovoID)
		{
			try{
				//aggiorno id su record chiamata
				Log.v("Update ID Rapportino", "IDRapportino: " + Integer.toString(ID));
				
				ContentValues cv = new ContentValues();
				cv.put(Rapportini.ID_KEY, nuovoID);
				Common.db.Update(Rapportini.TABLE_NAME, cv, Rapportini.ID_KEY + " = " + Integer.toString(ID), null);
				
				//aggiorno record rapportini dettagli
				List<RapportinoDettaglio> dettagli = RapportiniDettaglio.SelectAll(this.ID);
				if(dettagli != null && dettagli.size() > 0)
					for(RapportinoDettaglio d : dettagli)
						d.AggiornaIDRapportino(nuovoID);
				
				//aggiorno record rapportini tecnici
				List<RapportinoTecnici> tecnici = RapportiniTecnici.SelectAll(this.ID);
				if(tecnici != null && tecnici.size() > 0)
					for(RapportinoTecnici t : tecnici)
						t.AggiornaIDRapportino(nuovoID);
						
				return true;
			}
			catch(Exception e){ return false; }
		}
		public void AggiornaIDChiamata(int nuovoID)
		{
			//aggiorno id su record chiamata
			Common.db.executeSql("UPDATE "+ Rapportini.TABLE_NAME + " SET " + Rapportini.ID_CHIAMATA_KEY + " = " + Integer.toString(nuovoID) + " WHERE "+ Rapportini.ID_KEY + " = " + Integer.toString(this.ID));
		}
	}
}
